package com.handler.outbound;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.handler.utils.FileReader;
import com.to.MetaInfo;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
import io.netty.handler.codec.MessageToByteEncoder;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Random;

@Slf4j
public class MetaInfoEncoder extends ChannelOutboundHandlerAdapter {

    private ObjectMapper objectMapper = new ObjectMapper();


    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {

        MetaInfo metaInfo = (MetaInfo) msg;


        if (metaInfo.isAppendFile()) {

//            long totalFileSize = Files.size(Paths.get(metaInfo.getInputFilePath()));

//            long packageCount = totalFileSize / 65535 - initialCapacity;


//            long transactionId = new Random().nextLong();

//          FileReader.read(metaInfo.getInputFilePath(), buffer, metaInfo.getContinueTransportOffset());

            byte[] cache = new byte[60000];


            try (
                    RandomAccessFile file = new RandomAccessFile(metaInfo.getInputFilePath(), "r");) {

                long continueTransportOffset = metaInfo.getContinueTransportOffset();
                file.skipBytes((int) continueTransportOffset);


                int readLength = 0;

//                读取文件的同时上传文件，避免将整个问价加载到内存
                log.info("跳转到{}", continueTransportOffset);
                while ((readLength = file.read(cache)) != -1) {
                    ByteBuf buffer = writeHeadToByteBuf(ctx, metaInfo);
                    buffer.writeBytes(cache, 0, readLength);
//                    super.write(ctx, buffer, promise);
                    log.info("写入 {}", continueTransportOffset);
                    ctx.write(buffer);
                    continueTransportOffset += readLength;
                    metaInfo.setContinueTransportOffset(continueTransportOffset);
                }

//                发送已上传完成的消息
                metaInfo.setDone(true);
                ByteBuf buffer = writeHeadToByteBuf(ctx, metaInfo);
                ctx.write(buffer);
                log.info("写入完成");
                ctx.flush();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

        } else {
            ByteBuf buffer = writeHeadToByteBuf(ctx, metaInfo);
            super.write(ctx, buffer, promise);
        }

    }

    private ByteBuf writeHeadToByteBuf(ChannelHandlerContext ctx, MetaInfo metaInfo) throws JsonProcessingException {

        String metaInfoStr = objectMapper.writeValueAsString(metaInfo);

        byte[] metaInfoBytes = metaInfoStr.getBytes(StandardCharsets.UTF_8);

        int initialCapacity = 4 + metaInfoBytes.length;


        ByteBuf buffer = ctx.alloc().buffer(initialCapacity);

        buffer.writeInt(metaInfoBytes.length);

        buffer.writeBytes(metaInfoBytes);
        return buffer;
    }
}
